﻿using Abp.AspNetZeroCore;
using Abp.AspNetZeroCore.Web.Authentication.External;
using Abp.AspNetZeroCore.Web.Authentication.External.Facebook;
using Abp.AspNetZeroCore.Web.Authentication.External.Google;
using Abp.AspNetZeroCore.Web.Authentication.External.Microsoft;
using Abp.AspNetZeroCore.Web.Authentication.External.OpenIdConnect;
using Abp.Configuration.Startup;
using Abp.Dependency;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Abp.Threading.BackgroundWorkers;
using ARchGL.Platform.BackgroundWorker;
using ARchGL.Platform.Configuration;
using ARchGL.Platform.EntityFrameworkCore;
using ARchGL.Platform.MultiTenancy;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;

namespace ARchGL.Platform.Web.Startup
{
    [DependsOn(
        typeof(PlatformWebCoreModule)
    )]
    public class PlatformWebHostModule : AbpModule
    {
        private readonly IHostingEnvironment _env;
        private readonly IConfigurationRoot appConfiguration;

        public PlatformWebHostModule(
            IHostingEnvironment env)
        {
            _env = env;
            appConfiguration = env.GetAppConfiguration();
        }

        public override void PreInitialize()
        {
            Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat = appConfiguration["App:ServerRootAddress"] ?? "http://localhost:22742/";
            Configuration.Modules.AspNetZero().LicenseCode = appConfiguration["AbpZeroLicenseCode"];

            Configuration.BackgroundJobs.IsJobExecutionEnabled = false;
            Configuration.MultiTenancy.IsEnabled = bool.Parse(appConfiguration["Abp:MultiTenancyIsEnabled"]); //是否启用多租户
            Configuration.Auditing.IsEnabled = true; //启用日志
            Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = false; //向前端返回完整错误日志 _appConfiguration["ConnectionStrings:Tenant"].Contains("172.16.4.6");
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(PlatformWebHostModule).GetAssembly());
        }

        public override void PostInitialize()
        {
            using (var scope = IocManager.CreateScope())
            {
                if (!scope.Resolve<HostDatabaseCheckHelper>().Exist(appConfiguration["ConnectionStrings:Default"]))
                {
                    return;
                }
            }

            var workManager = IocManager.Resolve<IBackgroundWorkerManager>();
            workManager.Add(IocManager.Resolve<RefreshSpiderTokenWorker>()); //Spider服务，确保该服务在最前面，因为需要提前获取 Token
            workManager.Add(IocManager.Resolve<CleanExpireCacheWorker>());
            workManager.Add(IocManager.Resolve<ReportWarehousesWorker>());

            workManager.Add(IocManager.Resolve<WindowsServiceStatusWorker>()); //Windows 服务状态
            workManager.Add(IocManager.Resolve<CleanLockCacheWorker>()); //密码错误锁定自动任务
            workManager.Add(IocManager.Resolve<KeepLiveWorker>()); //持续运行不被回收

            //千变
            var flag = bool.TryParse(appConfiguration["Qianbian:IsEnabled"], out bool isEnabled);
            if (flag && isEnabled)
            {
                workManager.Add(IocManager.Resolve<QianbianSyncWorker>());
                workManager.Add(IocManager.Resolve<QianbianAttendancesSyncWorker>());
            }

            //第三方设备
            flag = bool.TryParse(appConfiguration["ThirdParty:Device:IsEnabled"], out isEnabled);
            if (flag && isEnabled)
            {
                workManager.Add(IocManager.Resolve<ThirdParty.RefreshTokenWorker>()); //刷新第三方 Token 服务
                workManager.Add(IocManager.Resolve<ThirdParty.SyncDataWorker>());
                workManager.Add(IocManager.Resolve<ThirdParty.ReportWorker>());
            }

            if (IocManager.Resolve<IMultiTenancyConfig>().IsEnabled)
            {
                workManager.Add(IocManager.Resolve<SubscriptionExpirationCheckWorker>());
                workManager.Add(IocManager.Resolve<SubscriptionExpireEmailNotifierWorker>());
            }
            workManager.Start();
            ConfigureExternalAuthProviders();
        }

        private void ConfigureExternalAuthProviders()
        {
            var externalAuthConfiguration = IocManager.Resolve<ExternalAuthConfiguration>();

            if (bool.Parse(appConfiguration["Authentication:OpenId:IsEnabled"]))
            {
                externalAuthConfiguration.Providers.Add(
                    new ExternalLoginProviderInfo(
                        OpenIdConnectAuthProviderApi.Name,
                        appConfiguration["Authentication:OpenId:ClientId"],
                        appConfiguration["Authentication:OpenId:ClientSecret"],
                        typeof(OpenIdConnectAuthProviderApi),
                        new Dictionary<string, string>
                        {
                            {"Authority", appConfiguration["Authentication:OpenId:Authority"] },
                            {"LoginUrl", appConfiguration["Authentication:OpenId:LoginUrl"] }
                        }
                    )
                );
            }

            if (bool.Parse(appConfiguration["Authentication:Facebook:IsEnabled"]))
            {
                externalAuthConfiguration.Providers.Add(
                    new ExternalLoginProviderInfo(
                        FacebookAuthProviderApi.Name,
                        appConfiguration["Authentication:Facebook:AppId"],
                        appConfiguration["Authentication:Facebook:AppSecret"],
                        typeof(FacebookAuthProviderApi)
                    )
                );
            }

            if (bool.Parse(appConfiguration["Authentication:Google:IsEnabled"]))
            {
                externalAuthConfiguration.Providers.Add(
                    new ExternalLoginProviderInfo(
                        GoogleAuthProviderApi.Name,
                        appConfiguration["Authentication:Google:ClientId"],
                        appConfiguration["Authentication:Google:ClientSecret"],
                        typeof(GoogleAuthProviderApi)
                    )
                );
            }

            //not implemented yet. Will be implemented with https://github.com/aspnetzero/aspnet-zero-angular/issues/5
            if (bool.Parse(appConfiguration["Authentication:Microsoft:IsEnabled"]))
            {
                externalAuthConfiguration.Providers.Add(
                    new ExternalLoginProviderInfo(
                        MicrosoftAuthProviderApi.Name,
                        appConfiguration["Authentication:Microsoft:ConsumerKey"],
                        appConfiguration["Authentication:Microsoft:ConsumerSecret"],
                        typeof(MicrosoftAuthProviderApi)
                    )
                );
            }
        }
    }
}
